#ifndef _FLV_H
#define _FLV_H

#ifdef  FLVAPI_EXPORTS
#define FLVAPI __declspec(dllexport)
#else
#define FLVAPI __declspec(dllimport)
#endif //*FLVAPI_EXPORTS

#include "buffer.h"

#define STREAM_VIDEO 9
#define STREAM_AUDIO 8
#define FLV_VERSION_1 1
#define FLV_FLAG_VIDEO 0x1
#define FLV_FLAG_AUDIO 0x4
#define FLV_TAG_TYPE_AUDIO 8
#define FLV_TAG_TYPE_VIDEO 9
#define FLV_FRAME_KEY 0x10
#define FLV_FRAME_INTER 0x20
#define FLV_FRAME_DISP 0x30
#define FLV_CODEC_SORENSEN 0x02
#define FLV_CODEC_SCREEN 0x03
#define FLV_TAG_HEADER_SIZE 11
#define FLV_TAG_DATA_OFFSET 12
#define FLV_AUDIO_FORMAT_UNCOMPRESSED	0
#define FLV_AUDIO_FORMAT_ADPCM		(1<<4)
#define FLV_AUDIO_FORMAT_MP3 		(2<<4)
#define FLV_AUDIO_FORMAT_NELLY_MONO	(5<<4)
#define FLV_AUDIO_FORMAT_NELLY		(6<<4)
#define FLV_SOUNDRATE_5KHZ		0
#define FLV_SOUNDRATE_11KHZ		(1<<2)
#define FLV_SOUNDRATE_22KHZ		(2<<2)
#define FLV_SOUNDRATE_44KHZ		(3<<2)
#define FLV_SOUNDSIZE_8			0
#define FLV_SOUNDSIZE_16		(1<<1)
#define FLV_SOUNDTYPE_STEREO		0
#define FLV_SOUNDTYPE_MONO		1
typedef unsigned char uc;

static enum  {
	OK,
	E_ERR,
	E_RW,
	E_HDR,
	E_FORMAT,
	E_STREAM,
	E_SEEK,
	E_EOF
};
static enum {
	BOTTOMUP,
	TOPDOWN
};
struct FLVAPI PixelData{
	int width;
	int height;
	/* padding (in bytes) at row-end */
	int rowPadding;
	/* number of channels per pixel 
	* RGB == 3
	* RGB + Alpha = 4
	*/
	int n_channels;
	/* rowOrder BOTTOMUP or TOPDOWN */
	char rowOrder;
	/* pixel data. [r, g, b [,alpha]) */
	uc *data;
};
struct FLVAPI VideoHDR{
	ui codec;
	ui frameType;
};
struct FLVAPI AudioHDR{
	uc format;
	uc samplingRate;
	uc sampleSize;
	uc channel;
};
class CStream;
struct FLVAPI Stream{
	int timestamp;
	int offset;
	int type;
	int (* writeData)(Stream *stream, CBuffer *buf, int *advance, void *data);
	int (* readData)(CStream *stream, CBuffer *buf,int *advance, void *data);
	void (* resetStream) (Stream *stream);
	void (* freeStream)(Stream *stream);
	union 
	{
		AudioHDR audio;
		VideoHDR video;
	} hdr;
};
struct FLVAPI FlvStream{
	uc flags;
	uc version;
	CStream *audio;
	CStream *video;
	CBuffer *buf;
};
struct FLVAPI FlvTag  {
	ui type;
	ui dataSize;
	ui timestamp;
	union
	{
		VideoHDR video;
		AudioHDR audio;
	} hdr;
	const unsigned char *data;
};

class FLVAPI CStream{
protected:
	CStream(){}
public:
	Stream m_stream;
	 void Free();
	void Rewind();
	static CStream *Create(int type);
};
class FLVAPI CFlvStream{
protected:
	CFlvStream(){}
public:
	FlvStream m_flvstream;
	static CFlvStream *Create(const char *name, CStream *audio, CStream *video, int version);
	CBuffer *GetBuffer();
	int FinishTag(FlvTag* tag);
	int WriteAudioTag(int tp, int len, void *data);
	int WriteVideoTag(int tp, int len, void *data);
	void Free();
	static CFlvStream *Open(const char *name);
	int WriteTag(FlvTag *tag);
	int ReadNextTag(FlvTag *tag);
};
#endif